<?php

Raise::load('db.core.RaiseDbModel');

/**
 * TestDbRaiseDbModel class
 * Testing unit of 'phpraise/db/RaiseDbModel.php'
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.UnitTest.Test
 */
class TestDbRaiseDbModel extends RaiseTest {

    public static function testClass(){
        self::assertClassExists('RaiseDbModel');
        self::assertClassExists('MockRaiseDbModel');

        self::assertClassIsAbstract('RaiseDbModel');
        self::assertClassExtends('MockRaiseDbModel', 'RaiseDbModel');

        self::assertClassMethod('RaiseDbModel', array(
            'fetch',
            'table',
            'isCompositePrimaryKey',
            'exists',
            'delete',
            'commit',
            'connection',
            'find',
            'findFirst'
        ));
    }

    private static function loadConnection(){
        $settings = new RaiseSettings('mocks/MockConfigFile.ini');

        $conn = new RaiseDbConnection($settings, 'default');
        return $conn;
    }

    public static function testGeneric(){
        $conn = self::loadConnection();
        $mock = new MockRaiseDbModel($conn);

        self::assertObjectClass($mock, 'MockRaiseDbModel');
        $mock->MockUserId = 5;
        self::assertFalse($mock->isCompositePrimaryKey());
        self::assertFalse($mock->exists());
    }

    public static function testInsertDelete(){
        $conn = self::loadConnection();
        $mock = new MockRaiseDbModel($conn);

        self::assertEqual($mock->count(), 0);
        self::assertFalse($mock->isCompositePrimaryKey());
        self::assertFalse($mock->exists());
        $mock->Name = 'testName';
        $mock->commit();

        self::assertType($mock->DateTimeCreated, 'object');
        self::assertObjectClass($mock->DateTimeCreated, 'RaiseDateTime');
        self::assertStrictEqual($mock->DateTimeCreated->date()->year(), RaiseDateTime::now()->date()->year());
        self::assertStrictEqual($mock->DateTimeCreated->date()->month(), RaiseDateTime::now()->date()->month());
        self::assertStrictEqual($mock->DateTimeCreated->date()->day(), RaiseDateTime::now()->date()->day());
        self::assertStrictEqual($mock->DateTimeCreated->time()->hour(), RaiseDateTime::now()->time()->hour());
        self::assertStrictEqual($mock->DateTimeCreated->time()->minute(), RaiseDateTime::now()->time()->minute());

        self::assertType($mock->DateTimeModified, 'object');
        self::assertObjectClass($mock->DateTimeModified, 'RaiseDateTime');
        self::assertStrictEqual($mock->DateTimeModified->date()->year(), RaiseDateTime::now()->date()->year());
        self::assertStrictEqual($mock->DateTimeModified->date()->month(), RaiseDateTime::now()->date()->month());
        self::assertStrictEqual($mock->DateTimeModified->date()->day(), RaiseDateTime::now()->date()->day());
        self::assertStrictEqual($mock->DateTimeModified->time()->hour(), RaiseDateTime::now()->time()->hour());
        self::assertStrictEqual($mock->DateTimeModified->time()->minute(), RaiseDateTime::now()->time()->minute());

        self::assertEqual($mock->MockUserId, 1);
        self::assertTrue($mock->exists());

        $mock2 = new MockRaiseDbModel($conn);
        $mock2->MockUserId = 1;
        $o = $mock2->fetch();
        
        $o = $o->get('MockRaiseDbModel');
        
        self::assertType($o->DateTimeCreated, 'object');
        self::assertObjectClass($o->DateTimeCreated, 'RaiseDateTime');

        self::assertStrictEqual($o->Name, 'testName');
        $o->Name = 'testName2';
        $o->commit();

        $o = $mock->fetch();
        $mock = $o->get('MockRaiseDbModel');
        self::assertStrictEqual($mock->Name, 'testName2');

        self::assertEqual($mock->count(), 1);

        $mock3 = new MockRaiseDbModel($conn);
        $mock3->Name = 'testingMyName';
        $mock3->commit();

        $model = new MockRaiseDbModel($conn);
        $c = $model->find(new RaiseDbSqlQueryCondition());
        self::assertStrictEqual($c->count(), 2);
        self::assertStrictEqual($c[0]['MockRaiseDbModel']->Name, 'testName2');
        self::assertStrictEqual($c[1]['MockRaiseDbModel']->Name, 'testingMyName');

        $d = $model->findFirst(new RaiseDbSqlQueryCondition());
        self::assertEqual($d['MockRaiseDbModel']->MockUserId, 1);
        self::assertStrictEqual($d['MockRaiseDbModel']->Name, 'testName2');

        $cond = new RaiseDbSqlQueryCondition();
        $cond->order()->add(new RaiseDbSqlOrder('MockUserId', 'DESC'));
        $d = $model->findFirst($cond);
        self::assertEqual($d['MockRaiseDbModel']->MockUserId, 2);
        self::assertStrictEqual($d['MockRaiseDbModel']->Name, 'testingMyName');
    }
    
    public static function testRelationship(){
        $conn = self::loadConnection();
        
        $user = new MockRaiseDbModel($conn);
        $user->Name = 'Sam';
        $user->commit();
        
        $cat = new MockRaiseDbModelCategory($conn);
        $cat->Name = 'Tester';
        $cat->commit();
        
        // insert relationship
        $cmd = new RaiseDbCommand($conn, 'INSERT INTO ' . strtolower(RaiseDbSqlIdentifier::field('UserInCategory', $conn)) . ' (MockUserId, MockCategoryId) VALUES (@UserId, @CategoryId)');
        $cmd->params()->add('@UserId', $user->MockUserId);
        $cmd->params()->add('@CategoryId', $cat->MockCategoryId);
        $cmd->executeNonQuery();
        
        $findings = $cat->fetch();
        
        self::assertObjectClass($findings['MockRaiseDbModelCategory'], 'MockRaiseDbModelCategory');
        self::assertStrictEqual($findings['MockRaiseDbModelCategory']->Name, $cat->Name);
        self::assertObjectClass($findings['MockRaiseDbModel'], 'RaiseCollection');
        self::assertStrictEqual($findings['MockRaiseDbModel']->count(), 1);
        self::assertObjectClass($findings['MockRaiseDbModel'][0], 'MockRaiseDbModel');
        self::assertStrictEqual($findings['MockRaiseDbModel'][0]->Name, $user->Name);
    }
    
    public static function unload(){
        $conn = self::loadConnection();
        $mock = new MockRaiseDbModel($conn);
        $mock2 = new MockRaiseDbModelCategory($conn);
        $cmd = new RaiseDbCommand($conn, 'TRUNCATE TABLE ' . RaiseDbSqlIdentifier::field($mock->table(), $conn) . '');
        $cmd->executeNonQuery();
        $cmd = new RaiseDbCommand($conn, 'TRUNCATE TABLE ' . RaiseDbSqlIdentifier::field('UserInCategory', $conn) . '');
        $cmd->executeNonQuery();
        $cmd = new RaiseDbCommand($conn, 'TRUNCATE TABLE ' . RaiseDbSqlIdentifier::field($mock2->table(), $conn) . '');
        $cmd->executeNonQuery();
    }

}
